/**
 * Copyright (C) 2009, 2010 SC 4ViewSoft SRL
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cc.mango.android.chart;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.text.DecimalFormat;

import org.achartengine.chart.AbstractChart;
import org.achartengine.chart.ScatterChart;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.DefaultRenderer;
import org.achartengine.renderer.SimpleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYMultipleSeriesRenderer.Orientation;
import org.achartengine.util.MathHelper;

import cc.telecomdigital.tdstock.Framework.UniqueItem.TDStockLog;
import cc.telecomdigital.tdstock.activity.chart.NvChart;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.view.MotionEvent;
import static cc.mango.android.chartutil.ChartCommons.*;

/**
 * The XY chart rendering class.
 */
public abstract class BaseXYChart extends AbstractChart
{
	/** The multiple series dataset. */
	protected XYMultipleSeriesDataset	mDataset;
	/** The multiple series renderer. */
	protected XYMultipleSeriesRenderer	mRenderer;

	/** The visible chart area, in screen coordinates. */
	protected Rect					screenR;
	/** The calculated range. */
	protected double[]				calcRange				= new double[4];

	protected double				xPixelsPerUnit			= 0;
	protected double				yPixelsPerUnit			= 0;

	protected NvChart				nvChart;

	//bottom size
	int							bottomHeight;
	//left size
	int							leftWidth;
	//right size
	int							rightWidth;
	//top size
	int							topHeight;

	List<String>					xLabels;

	List<String>					yLabels;

	List<Float>					xLabelLocations;

	List<Float>					yLabelLocations;

	//label 要平移的距离
	float						leftMargin			= 10;
	float						bottomMargin			= 30;

	//X坐标起始位置的索引
	List<Integer>					xLabelIndexs;

	//y label 要往下一的部分

	protected float				upChartYDropHeight		= 5;

	protected float				downChartYDropHeight	= 5;

	/**
	 * Builds a new XY chart instance.
	 * 
	 * @param dataset the multiple series dataset
	 * @param renderer the multiple series renderer
	 */
	public BaseXYChart(XYMultipleSeriesDataset dataset,
			XYMultipleSeriesRenderer renderer)
	{
		mDataset = dataset;
		mRenderer = renderer;
	}

	public BaseXYChart(XYMultipleSeriesDataset dataset,
			XYMultipleSeriesRenderer renderer, NvChart nvChart)
	{
		// TODO Auto-generated constructor stub
		mDataset = dataset;
		mRenderer = renderer;
		this.nvChart = nvChart;
	}

	/**
	 * The graphical representation of the series values as text.
	 * 
	 * @param canvas the canvas to paint to
	 * @param series the series to be painted
	 * @param paint the paint to be used for drawing
	 * @param points the array of points to be used for drawing the series
	 * @param seriesIndex the index of the series currently being drawn
	 */
	protected void drawChartValuesText(Canvas canvas, XYSeries series,
			Paint paint, float[] points, int seriesIndex)
	{
		for (int k = 0; k < points.length; k += 2)
		{
			//      drawText(canvas, getLabel(series.getY(k / 2)), points[k], points[k + 1] - 3.5f, paint, 0);
		}
	}

	/**
	 * The graphical representation of a text, to handle both HORIZONTAL and
	 * VERTICAL orientations and extra rotation angles.
	 * 
	 * @param canvas the canvas to paint to
	 * @param text the text to be rendered
	 * @param x the X axis location of the text
	 * @param y the Y axis location of the text
	 * @param paint the paint to be used for drawing
	 * @param extraAngle the array of points to be used for drawing the series
	 */
	protected void drawText(Canvas canvas, String text, float x, float y,
			Paint paint, int extraAngle)
	{
		int angle = -mRenderer.getOrientation().getAngle() + extraAngle;
		if (angle != 0)
		{
			// canvas.scale(1 / mScale, mScale);
			canvas.rotate(angle, x, y);
		}
		canvas.drawText(text, x, y, paint);
		if (angle != 0)
		{
			canvas.rotate(-angle, x, y);
			// canvas.scale(mScale, 1 / mScale);
		}
	}

	/**
	 * The graphical representation of a series.
	 * 
	 * @param canvas the canvas to paint to
	 * @param paint the paint to be used for drawing
	 * @param points the array of points to be used for drawing the series
	 * @param seriesRenderer the series renderer
	 * @param yAxisValue the minimum value of the y axis
	 * @param seriesIndex the index of the series currently being drawn
	 */
	protected abstract void drawSeries(Canvas canvas, Paint paint,
			float[] points, SimpleSeriesRenderer seriesRenderer,
			float yAxisValue, int seriesIndex);

	/**
	 * Returns if the chart should display the points as a certain shape.
	 * 
	 * @param renderer the series renderer
	 */
	protected abstract boolean isRenderPoints(SimpleSeriesRenderer renderer);

	protected void drawVerticalLine(Canvas canvas, float x, float top,
			int bottom)
	{
		Paint paint = new Paint();
		paint.setColor(INDICATOR_VERTICLAL_LINE_COLOR);
		paint.setStrokeWidth(LINE_WIDTH);
		paint.setAntiAlias(true);
		canvas.drawLine(x, bottom, x, top - 1, paint);
	}

	public boolean handleTouch(MotionEvent event)
	{
		float newX = event.getX();
		float newY = event.getY();
		switch (event.getAction())
		{
			case MotionEvent.ACTION_DOWN:

				if (isInRect((int) newX, (int) newY))
				{

					int index = getXIndex(newX, screenR.left);
					setIndex(index);
					setIsTouching(true);
					refreshView();
					TDStockLog.d("Print_Info", "newX:" + newX + "   index:"
							+ getIndex());
				}

				break;
			case MotionEvent.ACTION_MOVE:

				if (getIsTouching() && isInRect((int) newX, (int) newY))
				{//isTouching   and  in rect

					int index = getXIndex(newX, screenR.left);
					if (getIndex() != index)
					{
						setIndex(index);
						refreshView();
					}

					TDStockLog.d("Print_Info", "newX:" + newX + "   index:"
							+ getIndex());
					TDStockLog.d("Print_Info", "left:" + screenR.left);

				}

				break;
			case MotionEvent.ACTION_UP:

				setIsTouching(false);
				setIndex(0);
				refreshView();
				TDStockLog.d("Print_Info", "newX:" + newX + "   index:"
						+ getIndex());
				break;

		}

		return false;

	}

	protected boolean isInRect(int x, int y)
	{

		return screenR.left < screenR.right
				&& screenR.top < screenR.bottom // check for empty first
				&& x >= screenR.left && x <= screenR.right
				&& y >= screenR.top && y < screenR.bottom;
	}

	protected void setIsTouching(boolean b)
	{
		nvChart.setIsTouching(b);
	}

	protected boolean getIsTouching()
	{
		return nvChart.getIsTouching();
	}

	protected int getXIndex(float x, int left)
	{
		int index = (int) Math.round((x - left) / xPixelsPerUnit);

		XYSeries series = mDataset.getSeriesAt(0);

		int count = series.getItemCount();

		if (index < 0)
		{
			index = 0;
		}
		else if (index >= count)
		{
			index = count - 1;
		}

		return index;
	}

	protected void refreshView()
	{
		nvChart.refreshView();
	}

	protected float getXLocation(int index)
	{
		float xLocation = (float) (index * xPixelsPerUnit + screenR.left);
		return xLocation;
	}

	protected void setIndex(int index)
	{
		nvChart.setIndex(index);

	}

	protected int getIndex()
	{
		int count = mDataset.getSeriesAt(0).getItemCount();

		int index = nvChart.getIndex();

		if (index < 0)
		{
			index = 0;
		}
		else if (index >= count)
		{
			index = count - 1;
		}

		return index;
	}

	public void setNvChart(NvChart nvChart)
	{

		this.nvChart = nvChart;

	}

	//初始化图表的长宽高等数据
	public abstract void initSize(int width, int height);

	protected List<Float> getYLabelLocations(float y1, float y2, int numLabels)
	{

		if (yLabelLocations != null)
		{

			return yLabelLocations;
		}

		yLabelLocations = new ArrayList<Float>();

		if (numLabels < 2)
		{
			//		    	numLabels = 2;

			yLabelLocations.add(y1);

			return yLabelLocations;
		}

		if (y1 > y2)
		{

			float temp = y1;
			y1 = y2;
			y2 = temp;
		}

		float step = (y2 - y1) / (numLabels - 1);

		float yTemp = 0;

		for (int i = 0; i < numLabels; i++)
		{

			yTemp = y2 - i * step;
			yLabelLocations.add(yTemp);
		}

		return yLabelLocations;

	}

	//	  protected abstract List<Float> getXLabelLocations(float y1, float y2, int numLabels);

	protected abstract List<String> getYLabels(final double start,
			final double end, int numLabels);

	@Override
	public void drawLegendShape(Canvas canvas, SimpleSeriesRenderer renderer,
			float x, float y, Paint paint)
	{
		// TODO Auto-generated method stub

	}

	@Override
	public int getLegendShapeWidth()
	{
		// TODO Auto-generated method stub
		return 0;
	}

	//	  protected abstract List<String> getYLabels();//up
	//	  protected abstract String getYValue(int index);//up

	protected boolean isEqual(double d1, double d2)
	{

		return Math.abs(d1 - d2) < 0.000001;
	}

	protected void drawYLabels(Canvas canvas, Paint paint)
	{

		upChartYDropHeight = paint.getFontMetrics(new FontMetrics()) / 5;

		leftMargin = paint.measureText("00");

		TDStockLog.d("Print_Info", "leftMargin: " + leftMargin);

		if (mRenderer.isShowYlabels())
		{

			yLabels = getYLabels(calcRange[2], calcRange[3], mRenderer
					.getYLabels());

			yLabelLocations = getYLabelLocations(screenR.bottom,
					screenR.top, yLabels.size());

			int length = yLabels.size();

			for (int i = 0; i < length; i++)
			{
				String label = yLabels.get(i);
				float location = yLabelLocations.get(i);

				paint.setColor(mRenderer.getLabelsColor());
				paint.setTextAlign(Align.RIGHT);
				canvas.drawText(label, screenR.left - leftMargin, location
						+ upChartYDropHeight, paint);//ylabel 		                

			}

		}

	}

	/**
	 * Draws the chart background.
	 * 
	 * @param renderer the chart renderer
	 * @param canvas the canvas to paint to
	 * @param x the top left x value of the view to draw to
	 * @param y the top left y value of the view to draw to
	 * @param width the width of the view to draw to
	 * @param height the height of the view to draw to
	 * @param paint the paint used for drawing
	 */
	protected void drawBackground(DefaultRenderer renderer, Canvas canvas,
			int x, int y, int width, int height, Paint paint)
	{
		if (renderer.isApplyBackgroundColor())
		{
			paint.setColor(renderer.getBackgroundColor());
			paint.setStyle(Style.FILL);
			canvas.drawRect(x - 1f, y, x + width + 1f, y + height + 1f,
					paint);
		}
	}

	// 至少保留一位小数
	protected String getStringPrice(double source)
	{
		/* 
		 String s = StringUtils.formatToFiveCharsRuleWithoutSign(source + "");
		
		 if(s.length() < 4 && !s.contains(".")){
			 
			 s += ".0";
			 
		 }*/

		//			 String s = formatToNChars(source, 5);

		int n = 6;

		String s = formatToNChars(source, n);

		if (s.length() < (n - 1) && !s.contains("."))
		{

			s += ".0";

		}

		return s;
	}

	protected String formatToNChars(double value, int n)
	{

		String svalue = value + "";

		//长度小于n，直接返回
		if (svalue.length() <= n)
		{

			return svalue;
		}

		String sinteger = Math.round(value) + "";

		//整数长度超过n - 1时，直接返回整数，不会出现“1.”这样的数字
		if (sinteger.length() >= n - 1)
		{

			return sinteger;

		}

		TDStockLog.d("Print_Info", "value: " + value);

		//小数位数
		int digitNum = n - sinteger.length() - 1;

		//			 float temp = (float) Math.pow(10, digitNum);

		double temp = Math.pow(10, digitNum);

		value *= temp;

		TDStockLog.d("Print_Info", "value: " + value);

		String result = Math.round(value) / temp + "";

		TDStockLog.d("Print_Info", "result: " + result);

		return result;
	}

}
